﻿#include "pch.h"
#include "qgp/qgach.h"
#include "qg_blits.h"

#ifndef QG_NO_TGA

namespace _img
{
#include "extend/sbpackenter.h"
	struct FileHdrTGA
	{
		kbyte			IdLength;
		kbyte			ColorMapType;
		kbyte			ImageType;
		kbyte			FirstEntryIndex[2];
		kushort			ColorMapLength;
		kbyte			ColorMapEntrySize;
		kbyte			XOrigin[2];
		kbyte			YOrigin[2];
		kushort			ImageWidth;
		kushort			ImageHeight;
		kbyte			PixelDepth;
		kbyte			ImageDescriptor;
	} K_PACKED;

	struct FileFtrTGA
	{
		kuint			ExtensionOffset;
		kuint			DeveloperOffset;
		char			Signature[18];
	} K_PACKED;
#include "extend/sbpackleave.h"

	//
	class ImageWriterTga : public qbFsWriter, public tpl::MemAlloc<>
	{
	public:
		K_OVR void Dispose()
		{
			delete this;
		}

		K_OVR bool Test(const char* ext)
		{
			return k_strieqv(ext, "tga") != 0;
		}

		K_OVR bool Write(kStream* st, kObj* ctnr, kint mask)
		{
			// 컨테이너 검사
			qgImage* img = kCrbs::CastLinear<qgImage>(ctnr);

			if (img == NULL)
			{
				// 이거 이미지가 아님
				return false;
			}

			// 구성 검사
			const qbPixelProp& prop = img->GetPixelProp();

			if (prop.fmt != QGCF32_RGB && prop.fmt != QGCF32_RGBA &&
				prop.fmt != QGCF32_BGR && prop.fmt != QGCF32_BGRA)
				return false;

			kint pitch = img->GetPitch();
			kint width = img->GetWidth();
			kint height = img->GetHeight();

			//
			FileHdrTGA hdr;
			hdr.IdLength = 0;
			hdr.ColorMapType = 0;
			hdr.ImageType = 2;
			hdr.FirstEntryIndex[0] = 0;
			hdr.FirstEntryIndex[1] = 0;
			hdr.ColorMapLength = 0;
			hdr.ColorMapEntrySize = 0;
			hdr.XOrigin[0] = 0;
			hdr.XOrigin[1] = 0;
			hdr.YOrigin[0] = 0;
			hdr.YOrigin[1] = 0;
			hdr.ImageWidth = (kushort)width;
			hdr.ImageHeight = (kushort)height;
			hdr.ImageDescriptor = (1 << 5) | (1 << 3);
			hdr.PixelDepth = prop.bpp * 8;

			if (st->Write(&hdr, 0, sizeof(FileHdrTGA)) != sizeof(FileHdrTGA))
				return false;

			//
			kuint* data = (kuint*)img->GetData();
			kint x, y;

			if (prop.flags & QGCFF_BGR)
			{
				kuint* line = k_new(width, kuint);

				for (y = 0; y < height; y++)
				{
					kuint* p = (kuint*)(data + width*y);

					for (x = 0; x < width; x++)
						line[x] = qgColorWork::TRN_BGRA32_RGBA32(p[x]);

					if (st->Write(line, 0, pitch) != pitch)
						break;
				}

				k_delete(line);
			}
			else
			{
				for (y = 0; y < height; y++)
				{
					kuint* p = (kuint*)(data + width*y);

					if (st->Write(p, 0, pitch) != pitch)
						break;
				}
			}

			//
			FileFtrTGA ftr;
			ftr.ExtensionOffset = 0;
			ftr.DeveloperOffset = 0;
			memcpy(ftr.Signature, "TRUEVISION-XFILE.", 18);

			if (st->Write(&ftr, 0, sizeof(FileFtrTGA)) != sizeof(FileFtrTGA))
				return false;

			return height <= y;
		}
	};

	//
	qbFsWriter* CreateWriterImageTga()
	{
		return new ImageWriterTga();
	}
}

#endif	// QG_NO_TGA
